/*
 * Copyright (C) 2014 Will Dignazio
 * platform.c
 */
#include <Python.h>
#include <pyepiphany.h>
#include <e-hal.h>
#include "internal.h"

/*
 * The platform information is somewhat standalone,
 * this provides information about the epiphany chip
 * on board. The SDK provies the values which should
 * be returned, but they may be assumed to be within
 * a certain value rane (int vs. unsigned int) due to
 * python restrictions.
 */

struct EpiphanyPlatform
{
	PyObject_HEAD
	e_platform_t	platform;	// Epiphany platform
	PyObject*	version;	// Version string object ptr
};

/* Python exposed members */
static EpiphanyMember platform_members[] = 
{
	{"row", T_INT, offsetof(EpiphanyPlatform, platform.row), 0, "Row of coordinates"},
	{"col", T_INT, offsetof(EpiphanyPlatform, platform.col), 0, "Col of coordinates"},
	{"rows", T_INT, offsetof(EpiphanyPlatform, platform.rows), 0, "Number of rows in platform"},
	{"cols", T_INT, offsetof(EpiphanyPlatform, platform.cols), 0, "Number of columns in platform"},
	{"num_chips", T_INT, offsetof(EpiphanyPlatform, platform.num_chips), 0, "Number of Epiphany chips"},
	{"num_emems", T_INT, offsetof(EpiphanyPlatform, platform.num_emems), 0, "Number of external memory segments"},
	{ NULL },
};

/* Version string needs python string wrapper */
static PyGetSetDef platform_getsetters[] = 
{
	{"version", (getter)getplatversion, NULL, "Platform version", NULL},
	{ NULL },
};

/*
 * Similiar to the platform object in the eSDK, I wish
 * to have a uniform object with which to contain a 
 * Platform. This type extension shall wrap around the
 * e_epiphany_t and serve ad the interface to its properties.
 */
PyTypeObject platform_type = 
{
	PyObject_HEAD_INIT(NULL)
	0,				/* ob_size */
	"epiphany.Platform",		/* tp_name */
	sizeof(EpiphanyPlatform),	/* tp_basicsize */
	0,				/* tp_itemsize */
	0,				/* tp_dealloc */
	0,				/* tp_print */
	0,                         	/* tp_getattr */
	0,                         	/* tp_setattr*/
	0,                         	/* tp_compare */
	0,                         	/* tp_repr */
	0,                         	/* tp_as_number */
	0,                         	/* tp_as_sequence */
	0,                         	/* tp_as_mapping */
	0,                         	/* tp_hash */
	0,                         	/* tp_call */
	0,                         	/* tp_str */
	0,                         	/* tp_getattro */
	0,                         	/* tp_setattro */
	0,                         	/* tp_as_buffer */
	Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
	"Epiphany objects",           	/* tp_doc */
	0,               		/* tp_traverse */
	0,               		/* tp_clear */
	0,               		/* tp_richcompare */
	0,               		/* tp_weaklistoffset */
	0,               		/* tp_iter */
	0,               		/* tp_iternext */
	0,		             	/* tp_methods */
	platform_members,             	/* tp_members */
	platform_getsetters,		/* tp_getset */
	0,                         	/* tp_base */
	0,                         	/* tp_dict */
	0,                         	/* tp_descr_get */
	0,                         	/* tp_descr_set */
	0,                         	/* tp_dictoffset */
	0,			 	/* tp_init */
	0,                         	/* tp_alloc */
	platform_type_new,           	/* tp_new */
};

/* new obj callback, called before init */
PyObject*
platform_type_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	EpiphanyPlatform *plat;

	plat = (EpiphanyPlatform*)type->tp_alloc(type, 0);
	if(type == NULL)
		return NULL;

	return (PyObject*)plat;
}

/* e_platform_get_info wrapper */
PyObject*
epiphany_get_platform_info(PyObject *self, PyObject *args)
{
	EpiphanyPlatform *plat;
	int ret;

	if(!PyArg_ParseTuple(args, "O", &plat))
		return NULL;

	ret = e_get_platform_info(&plat->platform);
	if(ret != E_OK)
		return NULL;

	return Py_BuildValue("i", ret);
}

/*
 * XXX: Does not initialize platform object.
 * Initialize the internal platform object within
 * the python C extension.
 */
void
initplatform(PyObject *parent)
{
	platform_type.tp_new = PyType_GenericNew;
	if(PyType_Ready(&platform_type) < 0)
		return;

	Py_INCREF(&platform_type);
	PyModule_AddObject(parent, "Platform", (PyObject*)&platform_type);
}

/* Get version object from Epiphany Platform */
PyObject*
getplatversion(EpiphanyPlatform *self, void *closure)
{
	return Py_BuildValue("s", self->platform.version);
}
